﻿using Grow.Utils.Exceptions;
using MessagePack;
using MessagePack.Resolvers;

namespace Grow.Binary.MessagePack
{
    public class BinaryContext : IBinaryContext
    {
        private readonly MessagePackSerializerOptions _messagePackSerializerOptions;
        public BinaryContext()
        {
            _messagePackSerializerOptions = ContractlessStandardResolver.Options
                .WithSecurity(MessagePackSecurity.UntrustedData);
        }

        public async Task<T?> DeserializeAsync<T>(byte[] byteArr, CancellationToken cancellationToken = default)
        {
            try
            {
                using MemoryStream memoryStream = new();
                memoryStream.Position = 0;

                _ = await memoryStream.ReadAsync(byteArr, 0, byteArr.Length, cancellationToken);
                return await MessagePackSerializer.DeserializeAsync<T>(memoryStream, _messagePackSerializerOptions, cancellationToken);
            }
            catch (Exception ex)
            {
                throw new GrowBinaryException(ex.Message);
            }
        }

        public async Task<byte[]> SerializeAsync<T>(T value, CancellationToken cancellationToken = default)
        {
            try
            {
                using MemoryStream memoryStream = new();
                await MessagePackSerializer.SerializeAsync(memoryStream, value, _messagePackSerializerOptions, cancellationToken);

                using StreamReader streamReader = new(memoryStream);
                return memoryStream.ToArray();
            }
            catch (Exception ex)
            {
                throw new GrowBinaryException(ex.Message);
            }
        }
    }
}
